import { Component, OnInit } from '@angular/core';
import { NzMessageService } from 'ng-zorro-antd';
import { NzModalService } from 'ng-zorro-antd/modal';
import { DataRegister } from 'src/app/models';
import { BaseService, DataRegisterService } from 'src/app/services';
import { AddressService } from 'src/app/services/address.service';
import { EventManagerService } from 'src/app/services/event-manager.service';
import { OrganizationService } from 'src/app/services/organization.service';
import { UploadService } from 'src/app/services/upload.service';
import { EngineService } from '../../../services/engine.service';
import { BaseFieldComponent } from '../base-field/base-field.component';
import { AddMemoItemComponent } from './add-memo-item/add-memo-item.component';
import { v4 as UUID } from 'uuid';
import { ExceptionHandler } from 'src/app/handler/exception.handler';
import * as dayjs from 'dayjs';

@Component({
  selector: 'zepride-calendar-memo',
  templateUrl: './calendar-memo.component.html',
  styleUrls: ['./calendar-memo.component.less']
})
export class CalendarMemoComponent extends BaseFieldComponent implements OnInit {

  currentDate: Date;
  tab: 'system' | 'person' = 'system';
  memoDataRegister: DataRegister;
  allSystemMemoItems: MemoItem[] = [];
  personMemoItems: MemoItem[] = [];
  systemMemoItems: MemoItem[] = [];
  maxLength = 3;
  holidayDates: HolidayDate[] = [];

  constructor(
    protected engineService: EngineService,
    protected baseSvr: BaseService,
    protected eventSvr: EventManagerService,
    protected orgSvr: OrganizationService,
    public uploadService: UploadService,
    protected msg: NzMessageService,
    public addSvr: AddressService,
    private modal: NzModalService,
    protected dataRegisterService: DataRegisterService
  ) {
    super(engineService, baseSvr, eventSvr, orgSvr, uploadService, msg, dataRegisterService);
  }

  async ngOnInit() {
    try {
      this.setCurrentDate();
      this.memoDataRegister = await this.getDataRegister();
      await this.getBindDataSourceData();
      this.groupMemoItemByTypeAndDate(this.memoDataRegister);
      this.holidayDates = await this.getHolidays();
    } catch (error) {
      ExceptionHandler.current.handleError(error);
    }
  }

  setCurrentDate() {
    this.currentDate = new Date();
  }

  changeTab(tab: 'system' | 'person') {
    if (this.tab === tab) {
      return;
    } else {
      this.tab = tab;
    }
  }

  addMemoItem() {
    const title = '个人';
    const modalRef = this.modal.create({
      nzTitle: `添加${title}备忘`,
      nzFooter: null,
      nzContent: AddMemoItemComponent,
      nzComponentParams: {
        currentDate: this.currentDate
      }
    });
    modalRef.afterClose.subscribe(async (data: MemoItem) => {
      if (!data) {
        return;
      }
      const type = 'person';
      const id = UUID().replace(/-/g, '');
      const date = this.currentDate.getTime();
      const item: MemoItem = {
        ...data,
        type,
        id,
        date
      };
      this.memoDataRegister = await this.createDataRegister(item);
      this.groupMemoItemByTypeAndDate(this.memoDataRegister);
    });
  }

  getDataRegister() {
    const dataRegisterId = this.tmpComItemId;
    return this.dataRegisterService.getDataRegister(dataRegisterId);
  }

  createDataRegister(item?: MemoItem): Promise<DataRegister> {
    let data = [];
    if (this.memoDataRegister && this.memoDataRegister.data && this.memoDataRegister.data.length) {
      data = [...this.memoDataRegister.data, item];
    } else {
      data = [item];
    }
    const dataRegister: DataRegister = {
      id: this.tmpComItemId,
      dataType: 'memo',
      data,
      objectId: this.tmpComItemId,
      objectType: 'memo'
    };
    return this.dataRegisterService.createDataRegister(dataRegister, []);
  }
  /**
   * 获取个人备忘数据
   */
  groupMemoItemByTypeAndDate(dataRegister: DataRegister) {
    let personItems = [];
    if (dataRegister && dataRegister.data && dataRegister.data.length) {
      const data = dataRegister.data as MemoItem[];
      personItems = data.filter(item => {
        let isDate = false;
        if (item.date) {
          isDate = dayjs(this.currentDate).isSame(dayjs(item.date), 'day');
        }
        return item.type === 'person' && isDate;
      });
    }
    this.systemMemoItems = this.allSystemMemoItems.filter(item => {
      let isDate = false;
      if (item.date) {
        isDate = dayjs(this.currentDate).isSame(dayjs(item.date), 'day');
      }
      return isDate;
    });
    this.personMemoItems = personItems;
  }

  dateChange() {
    this.groupMemoItemByTypeAndDate(this.memoDataRegister);
  }

  getDataByDay(date: Date): MemoItem[] {
    if (!this.memoDataRegister || !this.memoDataRegister.data) {
      return [];
    } else if (this.tab === 'person') {
      const data = this.memoDataRegister.data as MemoItem[];
      return data.filter(item => {
        return dayjs(date).isSame(dayjs(item.date), 'day') && item.type === 'person';
      });
    } else if (this.tab === 'system') {
      const data = this.allSystemMemoItems;
      return data.filter(item => {
        return dayjs(date).isSame(dayjs(item.date), 'day');
      });
    }
  }

  async deleteItem(item: MemoItem) {
    try {
      if (this.memoDataRegister && this.memoDataRegister.data) {
        const data = this.memoDataRegister.data as MemoItem[];
        const index = data.findIndex(element => element.id === item.id);
        if (index > -1) {
          this.memoDataRegister.data.splice(index, 1);
          this.memoDataRegister = await this.dataRegisterService.createDataRegister(this.memoDataRegister, []);
          this.groupMemoItemByTypeAndDate(this.memoDataRegister);
        }
      }
    } catch (error) {
      ExceptionHandler.current.handleError(error);
    }
  }

  async getBindDataSourceData() {
    let systemMemoItems = [];
    if (this.componentData.extends && this.componentData.extends.memoConfig && this.componentData.extends.memoConfig.length) {
      for (const config of this.componentData.extends.memoConfig) {
        const dataSourceId = config.dataSourceId;
        const dataSource = await this.dataRegisterService.getDataSourceById(dataSourceId);
        const dataType = dataSource.dataType;
        if (dataType) {
          const data = await this.dataRegisterService.getComponentData({ dataType });
          const items = this.generateSystemMemoData(data, config);
          systemMemoItems = [...systemMemoItems, ...items];
        }
      }
    }
    this.allSystemMemoItems = systemMemoItems;
  }

  generateSystemMemoData(data: { list: any[] }, config: MemoConfig) {
    const result = [];
    if (data && data.list && data.list.length) {
      for (const item of data.list) {
        const field = config.bindField;
        let date = item[field];
        const isValid = this.isValidDate(date);
        if (!isValid) {
          continue;
        }
        let title = config.title;
        for (const spaceChar of config.titleSpaceChars) {
          const value = item[spaceChar.bindField];
          title = this.replaceContentByCode(title, spaceChar.code, value);
        }
        let content = config.content;
        for (const spaceChar of config.contentSpaceChars) {
          const value = item[spaceChar.bindField];
          content = this.replaceContentByCode(content, spaceChar.code, value);
        }
        date = date.date ? date.date : date;
        result.push({ title, content, date });
      }
    }
    return result;
  }

  replaceContentByCode(content: string, code: string, value: any) {
    if (!code) {
      return content;
    }
    code = code.replace(/\[/g, '\\\[').replace(/\]/g, '\\\]');
    const regExp = new RegExp(code, 'g');
    content = content.replace(regExp, value);
    return content;
  }

  isValidDate(value: any) {
    if (!value) {
      return false;
    }
    let timestamp: number;
    if (value.date) {
      timestamp = Date.parse(value.date);
    } else {
      timestamp = Date.parse(value);
    }
    return !isNaN(timestamp);
  }

  async getHolidays() {
    const originData = await this.dataRegisterService.getHolidays({ IsHoliday: 1 });
    let holidays = [];
    if (originData && originData.data && originData.data.result && originData.data.result.Data) {
      holidays = originData.data.result.Data;
    }
    return holidays;
  }

  checkIsHoliday(date: Date) {
    const isExist = this.holidayDates.find(holiday => {
      return dayjs(date).isSame(dayjs(holiday.Day), 'day');
    });
    return isExist ? true : false;
  }
}

interface MemoItem {
  type: 'system' | 'person';
  title: string;
  content: string;
  id: string;
  date: number;
  timeStart: Date;
  timeEnd: Date;
}

interface MemoConfig {
  content?: string;
  contentSpaceChars?: ContentSpaceChar[];
  dataSourceId?: string;
  title?: string;
  titleSpaceChars?: TitleSpaceChar[];
  bindField?: string;
}

interface ContentSpaceChar {
  code?: string;
  bindField?: string;
  tmpComItemId?: string;
}

interface TitleSpaceChar {
  code?: string;
  bindField?: string;
  tmpComItemId?: string;
}

interface HolidayDate {
  Day: string; // 2021-10-07 00:00:00
  Des: string;
  IsHoliday: 0 | 1;
  Month: string; // 2021-11
  Year: number; // 2021
}
